class MailFolder():
    """A convenience class representing a mail folder.

    This class delegates most operations to a MailStore instance.
    This is primarily useful in templates. String conversion
    returns the name of the folder. Read the documentation for the
    MailStore class to find out about these methods.

    Note: I am intentionally holding these as functions
    for the moment. These may be better as properties for further
    convenience.
    """
    _name = ''
    _ms = None

    def __init__(self, name, ms):
        self._name = name
        self._ms = ms

    def __str__(self):
        return self.name()

    def name(self):
        return self._name

    def parent(self):
        return self._ms.parent(self._name)

    def children(self):
        return self._ms.children(self._name)

    def total(self):
        return self._ms.total(self._name)

    def unread(self):
        return self._ms.unread(self._name)

    def message(self, uid):
        return self._ms.message(self._name, uid)

    def messages(self, start, count):
        return self._ms.messages(self._name, start, count)

class MailStore():
    """MailStore represents a mail storage service.

    This is an abstract class.

    A generic MailStore provides a high level interface for controllers
    to use in views, so they may remain agnostic as to the mail protocol
    in use.
    """

    def login(self, username, password):
        raise NotImplementedError

    def logout(self):
        raise NotImplementedError

    def open(self, name):
        """Open a folder for use.

        name is a string representing the folder to open.

        Returns a MailFolder instance.
        """
        raise NotImplementedError

    def close(self):
        """Close a currently open folder.

        Returns nothing.
        """
        raise NotImplementedError

    def unread(self, name):
        """Get the number of unread messages in a folder.

        name is a string representing the folder.

        Returns an int indicating the number of unread messages.
        On error zero is returned.
        """
        raise NotImplementedError

    def total(self, name):
        """Get the total number of messages in a folder.

        name is a string representing the folder.

        Returns an int representing the number of messages in the folder.
        On error it returns zero.
        """
        raise NotImplementedError

    def message(self, folder, uid):
        """Retrieve a message.

        folder is a string representing the folder of the message.
        uid is a string representing the message identifier.

        Returns a MailMessage instance.
        On error None is returned.
        """
        raise NotImplementedError

    def messages(self, name, start, count):
        """Get a range of messages.

        name is a string representing the folder to query.
        start is an int representing the first message to retrieve.
        count is an int representing the total number of messages to retrieve.

        Returns a list of MailMessage instances from the given folder.
        On error an empty list is returned.
        """
        raise NotImplementedError

    def namespaces(self):
        """Return a list of folder namespaces.

        It is unclear that this should exist in this class.
        """
        raise NotImplementedError

    def folders(self, namespace=None):
        """Return a list of MailFolder instances representing available folders.
        """
        raise NotImplementedError

    def children(self, name):
        """Get a list of child folders.
        
        name is a string representing the folder in question.

        Returns a list of MailFolder instances. An empty list will be
        returned if there are no child folders or the folder does not
        exist.
        """
        raise NotImplementedError

    def parent(self, name):
        """Return the parent of a folder
        
        name is a string representing the folder name.
        This will return a MailFolder or None.
        """
        raise NotImplementedError

